﻿#include "switchbutton.h"
#include "QStyleOption"
#include "QPainterPath"
#ifndef QT_NO_DEBUG
#include "QDebug"
#endif


SwitchButton::SwitchButton(QWidget *parent) :
    QWidget(parent)
{
    init();
}

void SwitchButton::init()
{
    // 初始化
    connect(this, &SwitchButton::posMoved, this, [&](){
        this->update();
    });

    m_State = false;

    m_Interval = 100;

    m_OnStateBackgroundColor = QColor(0, 200, 0);
    m_OffStateBackgroundColor = QColor(100, 100, 100);
    m_SwitchColor = QColor(255, 255, 255);
    m_StateLabelColor = QColor(240, 240, 240);
    m_StateLabelLineWidth = 2;
    m_OnStateRectBorderWidth = 6;    

    m_StateLabelLength = this->height() / 3;

    if (m_State) {
        quint8 dist = m_OnStateRectBorderWidth / 2;
        QRect right_rect(this->width() - this->height() + dist, dist, this->height() - m_OnStateRectBorderWidth, this->height() - m_OnStateRectBorderWidth);    // ON State
        setSwitchRect(right_rect);
    } else {
        QRect left_rect = QRect(0, 0, this->height(), this->height());
        setSwitchRect(left_rect);
    }

    // 设置背景透明
    setAttribute(Qt::WA_TranslucentBackground);
}



// 设置On状态时按钮背景颜色
void SwitchButton::setOnStateBackgroundColor(QColor color)
{
    m_OnStateBackgroundColor = color;

    return;
}

// 设置Off状态按钮背景颜色
void SwitchButton::setOffStateBackgroundColor(QColor color)
{
    m_OffStateBackgroundColor = color;

    return;
}


// 设置状态文字标签颜色
void SwitchButton::setStateLabelColor(QColor color)
{
    m_StateLabelColor = color;

    return;
}


// 获取圆形开关外切矩形
QRect SwitchButton::getSwitchRect()
{
    return m_SwitchRect;
}

// 设置圆形开关外切矩形
void SwitchButton::setSwitchRect(QRect rect)
{
    m_SwitchRect = rect;

    emit posMoved();

    return;
}


// 设置圆形开关颜色
void SwitchButton::setSwitchColor(QColor color)
{
    m_SwitchColor = color;

    return;
}


// 设置开关动作时长
void SwitchButton::setSwitchMovingDuration(quint16 msecs)
{
    m_Interval = msecs;

    return;
}


// 设置状态文字标签线宽
void SwitchButton::setStateLabelLineWidth(quint8 width)
{
    m_StateLabelLineWidth = width;

    return;
}

// 设置On状态时圆形开关的外切矩形距离边界的距离
void SwitchButton::setOnStateRectBorderWidth(quint8 width)
{
    m_OnStateRectBorderWidth = width;

    return;
}

// 获取开关状态
bool SwitchButton::getSwtichState()
{
    return m_State;
}


// 设置开关状态
void SwitchButton::setSwitchState(bool state)
{
    if (m_State == state) return;

    m_State = state;

    QRect left_rect = QRect(0, 0, this->height(), this->height());
    quint8 dist = m_OnStateRectBorderWidth / 2;
    QRect right_rect(this->width() - this->height() + dist, dist, this->height() - m_OnStateRectBorderWidth, this->height() - m_OnStateRectBorderWidth);    // ON State

    if (m_State) setSwitchRect(right_rect);
    else setSwitchRect(left_rect);
    this->update();

    return;
}


QSize SwitchButton::sizeHint() const
{
    return QSize(50, 30);
}



void SwitchButton::paintEvent(QPaintEvent *event)
{
    QPainter tPainter(this);

    // 设置抗锯齿
    tPainter.setRenderHint(QPainter::Antialiasing);

    // 以下代码可以使得setStyleSheet函数生效
    QStyleOption tOpt;

    // 根据QT版本选择初始化函数
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
    tOpt.initFrom(this);
#else
    tOpt.init(this);
#endif

    style()->drawPrimitive(QStyle::PE_Widget, &tOpt, &tPainter, this);
    QWidget::paintEvent(event);

    setSwitchColor(m_SwitchColor);

    drawBackground(&tPainter);

    drawStateLabel(&tPainter);

    drawSwitch(&tPainter);

    return;

}

void SwitchButton::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event)

    if (m_State) {
        quint8 dist = m_OnStateRectBorderWidth / 2;
        setSwitchRect(QRect(this->width() - this->height() + dist, dist, this->height() - m_OnStateRectBorderWidth, this->height() - m_OnStateRectBorderWidth));                      // ON state
    }
    else  setSwitchRect(QRect(0, 0, this->height(), this->height()));         // OFF state

    m_StateLabelLength = this->height() / 3;

    this->update();

    return;
}


// 绘制按钮背景轮廓
void SwitchButton::drawBackground(QPainter* const painter)
{
    if (NULL == painter) {
#ifndef QT_NO_DEBUG
        qDebug() << "error: the param \"painter\" in function \"drawBackground\" is NULL";
#endif
        return;
    }

    painter->setPen(Qt::NoPen);

    // 计算外边框左边和右边半圆外切矩形
    QRect left_rect(0, 0, this->height(), this->height());
    QRect right_rect(this->width() - this->height(), 0, this->height(), this->height());

    // 计算左右半圆弧线起始角度
    int left_arc_start_angle = 90;
    int right_arc_start_angle = 270;

    // 计算半圆弧跨度
    int sweep_len = 180;

    QPainterPath path;

    path.moveTo(left_rect.left() + this->height() / 2, 0);
    path.arcTo(left_rect, left_arc_start_angle, sweep_len);
    path.lineTo(right_rect.left() + this->height() / 2, this->height());
    path.arcTo(right_rect, right_arc_start_angle, sweep_len);
    path.lineTo(left_rect.left() + this->height() / 2, 0);

    if (this->isEnabled() && m_State) {
        painter->fillPath(path, QBrush(m_OnStateBackgroundColor));
    } else if (!this->isEnabled()){
        painter->fillPath(path, QBrush(QColor(150, 150, 150)));
    } else {
        painter->fillPath(path, m_OffStateBackgroundColor);
    }

    return;
}


// 绘制按钮开关
void SwitchButton::drawSwitch(QPainter* const painter)
{    
    if (NULL == painter) {
#ifndef QT_NO_DEBUG
        qDebug() << "error: the param \"painter\" in function \"drawSwitch\" is NULL";
#endif
        return;
    }

    painter->setPen(Qt::NoPen);

    if (this->isEnabled()) painter->setBrush(QBrush(m_SwitchColor));

    else painter->setBrush(QBrush(QColor(200,200,200)));

    // if (m_State) {
    //     m_SwitchRect.setSize(QSize(this->height() - m_OnStateRectBorderWidth, this->height() - m_OnStateRectBorderWidth));
    // }

    painter->drawEllipse(m_SwitchRect);
    this->update();
    return;

}


// 绘制按钮中的状态文字标识，I/O
void SwitchButton::drawStateLabel(QPainter * const painter)
{
    if (NULL == painter) {
#ifndef QT_NO_DEBUG
        qDebug() << "error: the param \"painter\" in function \"drawStateLabel\" is NULL";
#endif
        return;
    }

    quint16 dist_x = this->width() - this->height() / 2 - m_StateLabelLength / 2;
    quint16 dist_y = this->height() / 2 - m_StateLabelLength / 2;
    QRect off_state_rect(dist_x, dist_y, m_StateLabelLength, m_StateLabelLength);

    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(QBrush(m_StateLabelColor), m_StateLabelLineWidth));

    if (m_SwitchRect.left() > this->height() / 2) {
        painter->drawLine(this->height() / 2, dist_y, this->height() / 2, dist_y + m_StateLabelLength);
        return;
    }
    if (m_SwitchRect.right() < dist_x + m_StateLabelLength / 2) {
        painter->drawEllipse(off_state_rect);
        return;
    }
    painter->drawLine(this->height() / 2, dist_y, this->height() / 2, dist_y + m_StateLabelLength);
    painter->drawEllipse(off_state_rect);
    return;
}


// 鼠标点击
void SwitchButton::mousePressEvent(QMouseEvent *event)
{
    QRect left_rect = QRect(0, 0, this->height(), this->height());
    quint8 dist = m_OnStateRectBorderWidth / 2;
    QRect right_rect(this->width() - this->height() + dist, dist, this->height() - m_OnStateRectBorderWidth, this->height() - m_OnStateRectBorderWidth);    // ON State

    // 开关动画设置
    QPropertyAnimation *animation = new QPropertyAnimation(this, "m_SwitchRect");

    connect(animation, &QPropertyAnimation::finished, animation, &QPropertyAnimation::deleteLater);

    //当鼠标左键按下，提示信息
    if(event->button()==Qt::LeftButton)
    {
        if (!this->isEnabled()) return;

        if (m_State) {  // ON -> OFF
            m_State = false;

            animation->setStartValue(right_rect);
            animation->setEndValue(left_rect);

            emit switchOff();

        } else {        // OFF -> ON
            m_State = true;

            animation->setStartValue(left_rect);
            animation->setEndValue(right_rect);

            emit switchOn();
        }
        animation->start();
        this->update();
    }
    return;

}
